#include <iostream>
#include <vector>
#include <queue>

using namespace std;

struct point
{
    int x,y;
    point(int t1,int t2)
    {
        x=t1,y=t2;
    }
    point()
    {
        point(-1,-1);
    }
    bool operator !=(point b)
    {
        return x!=b.x||y!=b.y?true:false;
    }
};
struct state
{
    point p;
    int dir;
    int trn;
    state(point t1,int t2,int t3)
    {
        p=t1,dir=t2;trn=t3;
    }
};
vector<point> v1[55];
int n,m;
int res;
int map[55][55];
bool done[55][55];
queue<state> q;

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void init()
{
    res=0;
    for(int i=0;i<55;i++)v1[i].clear();
}
bool dfs(state vs,state t)
{
        //printf("%d %d->%d %d trn:%d\n",vs.p.x,vs.p.y,t.p.x,t.p.y,t.trn);
        if(map[t.p.x][t.p.y]==map[vs.p.x][vs.p.y]&&vs.p!=t.p&&!done[t.p.x][t.p.y])
        {
           // printf("match %d %d->%d %d\n",vs.p.x,vs.p.y,t.p.x,t.p.y);
            res++;
            done[t.p.x][t.p.y]=true;
            return true;
        }
        done[t.p.x][t.p.y]=true;
        if(t.p.y+1<m&&!done[t.p.x][t.p.y+1]&&(!map[t.p.x][t.p.y+1]||map[t.p.x][t.p.y+1]==map[vs.p.x][vs.p.y]))
        {
            if(t.dir==1||t.trn<2)
            {
                dfs(vs,state(point(t.p.x,t.p.y+1),1,t.dir==1?t.trn:t.trn+1));
            }
        }
        if(t.p.x+1<n&&!done[t.p.x+1][t.p.y]&&(!map[t.p.x+1][t.p.y]||map[t.p.x+1][t.p.y]==map[vs.p.x][vs.p.y]))
        {
            if(t.dir==2||t.trn<2)
            {
                dfs(vs,state(point(t.p.x+1,t.p.y),2,t.dir==2?t.trn:t.trn+1));
            }
        }
        if(t.p.y-1>=0&&!done[t.p.x][t.p.y-1]&&(!map[t.p.x][t.p.y-1]||map[t.p.x][t.p.y-1]==map[vs.p.x][vs.p.y]))
        {
            if(t.dir==3||t.trn<2)
            {
                dfs(vs,state(point(t.p.x,t.p.y-1),3,t.dir==3?t.trn:t.trn+1));
            }
        }
        if(t.p.x-1>=0&&!done[t.p.x-1][t.p.y]&&(!map[t.p.x-1][t.p.y]||map[t.p.x-1][t.p.y]==map[vs.p.x][vs.p.y]))
        {
            if(t.dir==4||t.trn<2)
            {
                dfs(vs,state(point(t.p.x-1,t.p.y),4,t.dir==4?t.trn:t.trn+1));
            }
        }
        done[t.p.x][t.p.y]=false;
}

int main()
{
    while(cin>>n>>m)
    {
        init();
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                scanf("%d",&map[i][j]);
                if(map[i][j]) v1[map[i][j]].push_back(point(i,j));
            }
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++) if(map[i][j])
            {
                fill(done[0],done[0]+55*55,false);
                dfs(state(point(i,j),0,-1),state(point(i,j),0,-1));
            }
        cout<<res/2<<endl;
    }
    return 0;
}
/*
4 4
1 0 0 1
0 0 0 0
0 0 0 0
1 0 0 1
4 5
1 0 0 3 0
0 4 0 7 0
0 6 0 0 0
5 4 3 2 1

*/
